<?php

/**
 * Quick and easy logging class
 *
 * @package Nina
 * @author John Main <john@thedaddy.org>
 */
class Nina_Logger {

	/**
	* Log levels
	* @constant
	*/
	const EMERG = 0;
	const ALERT = 1;
	const CRIT = 2;
	const ERROR = 3;
	const WARN = 4;
	const NOTICE = 5;
	const INFO = 6;
	const DEBUG = 7;

	/**
	* Singleton instance of this class
	* @access protected
	* @var Nina_Logger 
	* @static
	*/
	protected static $logger;
	
	/**
	* The log file location
	* @access protected
	* @var string 
	*/
	protected $log_file;
	
	/**
	* The current log level
	* @access protected
	* @var integer 
	*/
	protected $log_level;
	
	/**
	* Verbose mode
	* @access protected
	* @var boolean 
	*/
	protected $verbose;
	
	/**
	* Email errors to webmaster
	* @access protected
	* @var boolean 
	*/
	protected $email_errors;
	
	/**
	* The available log levels
	* @access protected
	* @var array 
	*/
	protected $log_levels = array(
		'emerg' => self::EMERG,
		'emergency' => self::EMERG,
		'alert' => self::ALERT,
		'crit' => self::CRIT,
		'critical' => self::CRIT,
		'error' => self::ERROR,
		'err' => self::ERROR,
		'warn' => self::WARN,
		'warning' => self::WARN,
		'notice' => self::NOTICE,
		'info' => self::INFO,
		'information' => self::INFO,
		'log' => self::INFO,
		'debug' => self::DEBUG
	);

	/**
	* Constructor
	* @param string $log_level Log level
	*/
	public function __construct($log_level = false) {
		$reg = Nina_Registry::getInstance();
		$log_reg = $reg->getReference('logging');

		$this->log_file = ($log_reg->get('file')) ? $log_reg->get('file') : APP_ROOT.DIRECTORY_SEPARATOR.'nina.log';

		if(!$log_level)
			$log_level = $log_reg->get('level');

		$this->verbose = $log_reg->get('verbose');

		$this->email_errors = ($log_reg->get('email_errors') && defined('WEBMASTER'));

		$this->setLogLevel($log_level);	
		
		//Make the log file if it doesn't already exist
		if(!file_exists($this->log_file)) {
			if($file = @fopen($this->log_file, 'w'))
				fclose($file);
		}
	}
	
	/**
	* Writes log message to log file (or syslog) if the message level is less than or equal to the log level
	* @param integer $log_level Log level 
	* @param string $message The message to log 
	*/
	protected function logger($log_level, $message) {
		$date_message = date('Y-m-d H:i:s') . ' '. $message."\n";

		if($log_level <= $this->log_level) {
			//Try to write to log file, otherwise use syslog	
			if(!@file_put_contents($this->log_file, $date_message, FILE_APPEND))
				syslog($log_level, $message);
			
			if($this->verbose)
				echo $date_message;
			
			//Send error email to webmaster if applicable
			if($log_level <= self::ERROR && $this->email_errors) {
				$mail = new Nina_Mail('Error on ' . APP_NAME, false);
				$mail->setFrom(APP_NAME . ' System', WEBMASTER);
				$mail->addRecipient(WEBMASTER, APP_NAME . ' Webmaster');
				$mail->setMessage($date_message);
				$mail->send();
			}
		}
	}
	
	/**
	* Add line breaks to the log
	* @param integer $no_of_lines Number of line breaks to insert
	*/
	public function lineBreak($no_of_lines = 1) {
		$breaks = '';
		for($i=1; $i<=$no_of_lines; $i++) {
			$breaks .= "\n";
		}
	
		@file_put_contents($this->log_file, $breaks, FILE_APPEND);
	}
	
	/**
	* Sets a new log level
	* Pass log level as string or integer
	* @param mixed $log_level log level
	*/
	public function setLogLevel($log_level) {
		if(!is_numeric($log_level) && isset($this->log_levels[$log_level]))
			$log_level = $this->log_levels[$log_level];

		if(is_numeric($log_level) && $log_level < 8)
			$this->log_level = $log_level;
		else
			$this->log_level = SELF::WARN;
	}
	
	/**
	* Recevies and validates logger calls then passes them to be logged
	* @param string $log_level log level 
	* @param array $message The method arguments containing the message to log 
	*/
	public function __call($log_level, $message) {
		if(isset($this->log_levels[$log_level]) && count($message) > 0)
			$this->logger($this->log_levels[$log_level], $message[0]);
	}
	
	/**
	* Return a static instance of this class
	* @param string $log_level Log level
	* @return Aurora_Logger
	*/
	public static function getInstance($log_level = false) {
		if(!self::$logger)
			self::$logger = new self($log_level);
			
		return self::$logger;
	}
}

